#pragma once

#include <iostream>
#include <string>
#include <cstring>
#include <cerrno>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "err.hpp"

// V1版本：
// 功能：基础消息回响
// 核心：TCP协议的连接（监听、接收、连接）

namespace ns_server
{
    class TcpServer
    {
        static const uint16_t default_port = 8080;
        static const int backlog = 32; // TODO
    public:
        TcpServer(uint16_t port = default_port)
            : port_(port), quit_(true)
        {
        }

        ~TcpServer()
        {
        }

        void InitServer()
        {
            // 初始化服务器
            listen_sock_ = socket(AF_INET, SOCK_STREAM, 0); // 基于IPV4的流式数据传输
            if (listen_sock_ == -1)
            {
                std::cerr << "Create Sock Fail: " << strerror(errno) << std::endl;
                exit(SOCKET_ERR);
            }

            // 创建addr结构体（包含自己的端口号和IP信息）
            struct sockaddr_in local;
            memset(&local, 0, sizeof local);
            local.sin_family = AF_INET;
            local.sin_port = htons(port_);
            local.sin_addr.s_addr = INADDR_ANY; // 可以绑定任意ip

            // 绑定
            if (bind(listen_sock_, (struct sockaddr *)&local, sizeof local) == -1)
            {
                std::cerr << "Bind Sock Fail: " << strerror(errno) << std::endl;
                exit(BIND_ERR);
            }

            // 监听
            if (listen(listen_sock_, backlog) == -1)
            {
                std::cerr << "Listen Sock Fail: " << strerror(errno) << std::endl;
                exit(LISTEN_ERR);
            }
        }

        void service(const int& sock, const struct sockaddr_in& client)
        {
            //流式数据传输，可以使用文件操作相关接口
            char buff[1024];
            while(true)
            {
                //从客户端读取数据
                int n = read(sock, buff, sizeof(buff) - 1);
                if(n > 0) buff[n] = '\0';
                else continue;

                //处理数据（打印）
                std::string ip = inet_ntoa(client.sin_addr);
                uint16_t port = ntohs(client.sin_port);
                std::cout << "Client [" << ip << "-" << port << "] >> " << buff << std::endl;

                //回响数据
                write(sock, buff, strlen(buff));
            }
        }

        void StartServer()
        {
            quit_ = false; // 服务器运行，不退出
            while (!quit_)
            {
                // 连接
                struct sockaddr_in client; // 客户端信息
                socklen_t len = sizeof(client);
                int sock = accept(listen_sock_, (struct sockaddr *)&client, &len);
                if (sock == -1)
                {
                    std::cerr << "Accept Sock Fail: " << strerror(errno) << std::endl;
                    exit(ACCEPT_ERR);
                }
                std::cout << "Link Success! " << sock << " from " << listen_sock_ << std::endl;

                //提供服务
                service(sock, client);
            }
        }

    private:
        int listen_sock_; // 监听套接字
        uint16_t port_;   // 端口号
        bool quit_;       // 退出状态
    };
}